/*
 * Qt5-UKUI's Library
 *
 * Copyright (C) 2023, KylinSoft Co., Ltd.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this library.  If not, see <https://www.gnu.org/licenses/>.
 *
 * Authors: Yue Lan <lanyue@kylinos.cn>
 *
 */

#include "proxy-style-plugin.h"
#include "proxy-style.h"
#include "ukui-style-settings.h"

#include "application-style-settings.h"

#include "black-list.h"

#include <QApplication>
#include <QStyleFactory>
#include <QWidget>

#include <QDebug>
#include <QDBusConnection>
#include <QDBusInterface>
#include <QDBusConnection>
#include <QLayout>

using namespace UKUI;

#define blackStyleChangeApp "kylin-software-center"

ProxyStylePlugin::ProxyStylePlugin()
{
    if (UKUIStyleSettings::isSchemaInstalled("org.ukui.style")) {
        auto settings = UKUIStyleSettings::globalInstance();
        connect(settings, &UKUIStyleSettings::changed, this, [=](const QString &key) {
            if (key == "styleName" || key == "widgetThemeName" || key == "themeColor" ||
                    key == "style-name" || key == "widget-theme-name" || key == "theme-color") {
                if (blackList().contains(qAppName()) || qAppName() == "kylin-software-center.py")
                    return;

                //We should not swich a application theme which use internal style.
                if (QApplication::style()->inherits("InternalStyle"))
                    return;

                auto appStyleSettings = ApplicationStyleSettings::getInstance();
                if (appStyleSettings->currentStyleStretagy() != ApplicationStyleSettings::Default)
                    return;

                auto styleName = settings->get("styleName").toString();

                if (styleName == "ukui-default" || styleName == "ukui-dark" || styleName == "ukui-white"
                        || styleName == "ukui-black" || styleName == "ukui-light" || styleName == "ukui") {

                    if (styleName == "ukui")
                        styleName = "ukui-default";
                    else if (styleName == "ukui-black")
                        styleName = "ukui-dark";
                    else if (styleName == "ukui-white")
                        styleName = "ukui-light";


                    if (qApp->property("customStyleName").isValid()) {
                        if (qApp->property("customStyleName").toString() == "ukui-light") {
                            styleName = "ukui-light";
                        } else if (qApp->property("customStyleName").toString() == "ukui-dark") {
                            styleName = "ukui-dark";
                        }
                    }

                    if(m_style){
                        m_style->deleteLater();
                        m_style = nullptr;
                    }
                    m_style = new ProxyStyle(styleName);
                    qApp->setStyle(m_style);
                    return;
                }

                //other style
                for (auto keys : QStyleFactory::keys()) {
                    if (styleName.toLower() == keys.toLower()) {
                        if(m_style){
                            m_style->deleteLater();
                            m_style = nullptr;
                        }
                        m_style = new QProxyStyle(styleName);
                        qApp->setStyle(m_style);
                        return;
                    }
                }

                //default style fusion
                if(m_style){
                    m_style->deleteLater();
                    m_style = nullptr;
                }
                m_style = new QProxyStyle(styleName);
                qApp->setStyle(m_style);
                return;
            }

            if (key == "systemPalette") {
                onSystemPaletteChanged();
            }

            if (key == "useSystemPalette") {
                onSystemPaletteChanged();
            }
        });
    }

    QDBusInterface *interFace = new QDBusInterface("com.kylin.statusmanager.interface",
                                                   "/",
                                                   "com.kylin.statusmanager.interface",
                                                    QDBusConnection::sessionBus());
    if(interFace->isValid()){
        connect(interFace, SIGNAL(mode_change_signal(bool)), this,  SLOT(tableModeChanged(bool)));
    }
}

ProxyStylePlugin::~ProxyStylePlugin()
{
    if(m_style){
        m_style->deleteLater();
        m_style = nullptr;
    }
}

QStyle *ProxyStylePlugin::create(const QString &key)
{
    if (blackList().contains(qAppName()))
        return new QProxyStyle("fusion");
    if (key == "ukui") {
        if (UKUIStyleSettings::isSchemaInstalled("org.ukui.style")) {
            m_current_style_name = UKUIStyleSettings::globalInstance()->get("styleName").toString();
            m_current_theme_name = UKUIStyleSettings::globalInstance()->get("widgetThemeName").toString();

            if (m_current_style_name == "ukui-default" || m_current_style_name == "ukui-dark"
                    || m_current_style_name == "ukui-white" || m_current_style_name == "ukui-black"
                    || m_current_style_name == "ukui-light" || m_current_style_name == "ukui") {

                if (m_current_style_name == "ukui")
                    m_current_style_name = "ukui-default";
                else if (m_current_style_name == "ukui-black")
                    m_current_style_name = "ukui-dark";
                else if (m_current_style_name == "ukui-white")
                    m_current_style_name = "ukui-light";

                if (m_current_theme_name == "default" ||
                        m_current_theme_name == "classical" ||
                        m_current_theme_name == "fashion") {
                    qApp->setProperty("widgetThemeName", m_current_theme_name);
                } else {
                    qApp->setProperty("widgetThemeName", "default");
                }

                return new ProxyStyle(m_current_style_name);
            }

            for (auto styleName : QStyleFactory::keys()) {
                if (styleName.toLower() == m_current_style_name.toLower()){
                    return new QProxyStyle(m_current_style_name);
                }
            }
        }

        return new QProxyStyle("fusion");
    }

    return new QProxyStyle("fusion");
}

const QStringList ProxyStylePlugin::blackList()
{
    return blackAppList();
}

void ProxyStylePlugin::onSystemPaletteChanged()
{
    bool useSystemPalette = UKUIStyleSettings::globalInstance()->get("useSystemPalette").toBool();
    if (useSystemPalette) {
        auto data = UKUIStyleSettings::globalInstance()->get("systemPalette");
        if (data.isNull())
            return;
        auto palette = qvariant_cast<QPalette>(data);
        QApplication::setPalette(palette);
    } else {
        auto palette = QApplication::style()->standardPalette();
        QApplication::setPalette(palette);
    }
}

void ProxyStylePlugin::tableModeChanged(bool isTableMode)
{
    if (blackList().contains(qAppName()))
        return;

    //We should not swich a application theme which use internal style.
    if (QApplication::style()->inherits("InternalStyle"))
        return;

    auto appStyleSettings = ApplicationStyleSettings::getInstance();
    if (appStyleSettings->currentStyleStretagy() != ApplicationStyleSettings::Default)
        return;

    auto settings = UKUIStyleSettings::globalInstance();
    auto styleName = settings->get("styleName").toString();

    if (styleName == "ukui-default" || styleName == "ukui-dark" || styleName == "ukui-white"
            || styleName == "ukui-black" || styleName == "ukui-light" || styleName == "ukui")

    {
        if (qApp->property("customStyleName").isValid()) {
            if (qApp->property("customStyleName").toString() == "ukui-light") {
                styleName = "ukui-light";
            } else if (qApp->property("customStyleName").toString() == "ukui-dark") {
                styleName = "ukui-dark";
            }
        }

        foreach (QWidget *widget, qApp->allWidgets()) {
            widget->updateGeometry();
        }
        qApp->setProperty("isInitial", false);
        if(qAppName() != blackStyleChangeApp)
            qApp->setStyle(new ProxyStyle(styleName));
    }
    /*
    foreach (QObject *obj, qApp->children()) {
        if(qobject_cast<const QVBoxLayout*>(obj))//obj->inherits("QVBoxLayout"))
        {
            auto *vlayout = qobject_cast<QVBoxLayout *>(obj);
            qDebug() << "vlayout..." << vlayout->spacing();

            //layout->update();
        }
        else if(qobject_cast<QHBoxLayout *>(obj))
        {
            auto *hlayout = qobject_cast<QHBoxLayout *>(obj);
            qDebug() << "hlayout..." << hlayout->spacing();

            //layout->update();
        }
    }
    foreach (QWidget *widget, qApp->topLevelWidgets()) {
        qDebug() << "widget size...." << widget->size() << widget->minimumSizeHint() << widget->minimumSize();
        widget->adjustSize();
        if(widget->layout() != nullptr)
        {
            qDebug() << "layoutSpace...." << widget->layout()->spacing();
        }
//        if(widget->size() != widget->minimumSizeHint())
//            widget->setGeometry(widget->x(), widget->y(), widget->minimumSizeHint().width(), widget->minimumSizeHint().height());
    }
*/
    return;
}
